/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package games.mapacman.server;

import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;
import marauroa.common.game.IRPZone;
import marauroa.common.game.RPObject;

/**
 *
 * @author mehadihasan
 */
public class ZoneDivider {

    private static ZoneDivider instance;
    private HashMap<String, List<ZoneBox>> boundaryHash;
    List<String> availableIPs;
    boolean synced = false;
    private boolean migrate = false;

    public static ZoneDivider get() {
        if (instance == null) {
            instance = new ZoneDivider();
        }
        return instance;
    }

    public ZoneDivider() {
        this.boundaryHash = new HashMap<String, List<ZoneBox>>();

    }

    public boolean isMigrate() {
        return migrate;
    }

    public void setMigrate(boolean migrate) {
        this.migrate = migrate;
    }

    

    public List<String> getAvailableIPs() {
        return availableIPs;
    }

    public void setAvailableIPs(List<String> availableIPs) {
        this.availableIPs = availableIPs;
    }

    public boolean isSynced() {
        return synced;
    }

    public synchronized void setSynced(boolean synced) {
        this.synced = synced;
    }


    public String getIPBasedOnPosition(RPObject rPObject) {
        int x = rPObject.getInt("x");
        int y = rPObject.getInt("y");
        String zoneName = rPObject.get("zoneid");

        if (zoneName.compareTo("start") != 0) {
            return null;
        }
        List<ZoneBox> zoneBoxs = boundaryHash.get(zoneName);

        for (ZoneBox zoneBox : zoneBoxs) {
            if (isInArea(zoneBox, x, y)) {
                return zoneBox.getIp();
            }
        }
        return null;
    }

    public boolean isInArea(Rectangle zoneBox, int x, int y) {
        if (zoneBox.contains(x, y)) {
            return true;
        } else {
            return false;
        }
    }

    public ZoneBox createZoneBox(String zoneName, String ip, int x, int y, int width, int height) {


        ZoneBox tempZone = null;
        if (x >= 10) {
            x -= 10;
        } else {
            x = 0;
        }
        if (y >= 10) {
            y -= 10;
        } else {
            y = 0;
        }
        tempZone = new ZoneBox(x, y, width + 20, height + 20);
        tempZone.setIp(ip);
        synchronized (boundaryHash) {
            if (this.boundaryHash.get(zoneName) == null) {
                this.boundaryHash.put(zoneName, new ArrayList<ZoneBox>());
            }
            this.boundaryHash.get(zoneName).add(tempZone);
        }
        return tempZone;
    }

    public void incrementPopulation(RPObject rPObject) {
        int x = rPObject.getInt("x");
        int y = rPObject.getInt("y");
        String zoneName = rPObject.get("zoneid");

        if (zoneName.compareTo("start") != 0) {
            return;
        }
        List<ZoneBox> zoneBoxs = boundaryHash.get(zoneName);

        for (ZoneBox zoneBox : zoneBoxs) {
            if (isInArea(zoneBox, x, y)) {
                zoneBox.incrementPopulation();
                break;
            }
        }


    }

    public void resetPopulation() {
        for (String key : this.boundaryHash.keySet()) {
            for (ZoneBox zoneBox : this.boundaryHash.get(key)) {
                zoneBox.setPopulation(0);
            }
        }
    }

    public void divideZoneStrategy() {
        int i = 0;
        for (String key : this.boundaryHash.keySet()) {
            for (ZoneBox zoneBox : this.boundaryHash.get(key)) {
                if (zoneBox.getPopulation() > 5) {
                    if (i < this.getAvailableIPs().size()) {
                        zoneBox.setIp(this.getAvailableIPs().get(i));                        
                        i++;
                        migrate = true;
                    }
                }
            }
        }

    }

    public void createInitialZoneBoxes(String zoneName, int x, int y, int width, int height) {
        System.err.println(x + " " + y + " " + width + " " + height);
        System.err.println(this.createZoneBox(zoneName, "", x, y, width / 2, height / 2));
        System.err.println(this.createZoneBox(zoneName, "", x + width, y, width / 2, height / 2));
        System.err.println(this.createZoneBox(zoneName, "", x, y + height, width / 2, height / 2));
        System.err.println(this.createZoneBox(zoneName, "", x + width, y + height, width / 2, height / 2));

    }

    public boolean isInMyRegion(RPObject object) {

        int x = object.getInt("x");
        int y = object.getInt("y");
        String zoneName = object.get("zoneid");

        List<ZoneBox> zoneBoxs = boundaryHash.get(zoneName);

        for (ZoneBox zoneBox : zoneBoxs) {
            if (isInArea(zoneBox, x, y) && zoneBox.getIp().compareTo("") != 0) {
                return false;
            }
        }
        return true;


    }

    public synchronized boolean isInCommonRegion(RPObject object) {
        int x = object.getInt("x");
        int y = object.getInt("y");
        if (object.get("zoneid").compareTo("start") == 0 && isSynced()) {
            for (ZoneBox zonebox : boundaryHash.get("start")) {
                for (ZoneBox zonebox1 : boundaryHash.get("start")) {

                    if (zonebox1.getIp().compareTo("") != 0 || zonebox.getIp().compareTo("") != 0) {
                        Rectangle temp = zonebox.intersection(zonebox1);
                        if (isInArea(temp, x, y)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
//    public boolean borderBand(RPObject rPObject) {
//        int x = rPObject.getInt("x");
//        int y = rPObject.getInt("y");
//        String zoneName = rPObject.get("zoneid");
//
//        List<ZoneBox> zoneBoxs = this.boundaryHash.get(zoneName);
//
//    }
//
//    public int calculateProximity(ZoneBox z, int x, int y){
//        int x2 = (x - (int) z.getCenterX()) * (x - (int) z.getCenterX());
//        int y2 = (y - (int) z.getCenterY()) * (y - (int) z.getCenterY());
//
//        return (int) Math.sqrt(x2+y2);
//    }
}
